"""
This file is part of GSBEdit. For copyright and licensing information, please
see gsbedit.py in the GSBEdit base directory.
"""


import wx
import ui_elements.controls.attribute_control as ac
from ui_elements.panel_copy import attribute_panel_copy as copy
import sys


class AttributePanel(wx.Panel):
    def __init__(self, parent, panel_info, next_id, prevent_freeze = False):
        wx.Panel.__init__(self, parent)
        self.parent = parent
        self.prevent_freeze = prevent_freeze
        
        self.column_sizer = wx.BoxSizer(wx.HORIZONTAL)        
        
        self.module_info = {}
        self.module_values = {}
        self.changed_module_values = {}
        self.columns = 0
        
        self.SetSizer(self.column_sizer)
        self.next_id = self.set_panel_info(panel_info, next_id)
    
    
    def get_next_id(self):
        return self.next_id
    
    
    def set_panel_info(self, panel_info, next_id):
        if not(self.prevent_freeze): self.Freeze()
        self.panel_info = copy(panel_info)
                        
        self.columns = len(self.panel_info['controls'])
        for column in self.panel_info['controls']:
            for control in column:
                control['id'] = next_id
                control['object'] = self.create_control(control)
                control['object'].Hide()
                next_id += 1
        
        if not(self.prevent_freeze): self.Thaw()
        
        return next_id
    
    
    def set_module(self, module_info, module_values):
        # Don't bother making a local copy. It's not needed for the module
        # info, and we *want* value changes to be seen globally.
        self.modue_info = module_info
        self.module_values = module_values
        self.changed_module_values = {}
        
        for column in self.panel_info['controls']:
            for control in column:
                if type(control['object']) not in [wx.Button]:
                    control['object'].set_module(module_info, module_values)
                #self.conditions.append(control['condition'])
        
        self.update_display()
    
    
    def update_display(self):
        """Update the displayed panels based on the supplied module
        information.
        """
        if not(self.prevent_freeze): self.Freeze()
        self.column_sizer.Clear()
        
        for column in self.panel_info['controls']:
            captions = []
            current_column = wx.BoxSizer(wx.VERTICAL)
            self.column_sizer.Add(current_column, 1, wx.EXPAND)
            for control in column:
                if self.should_display_child(control):
                    current_column.Add(control['object'], 0, wx.EXPAND)
                    control['object'].Show()
                    captions.append(control['object'].caption)
                else:
                    control['object'].Hide()
            
            if len(captions) > 0:
                mins = [caption.GetBestSize()[0] for caption in captions]
                if len(mins) > 0:
                    maximum_x = max(mins)
                    for caption in captions:
                        caption.SetInitialSize(wx.Size(maximum_x, -1))
        
        self.Layout()
        if not(self.prevent_freeze): self.Thaw()

    """
    def evaluate_condition(self, condition, values=self.get_current_values()):
        key, op, value = condition.split(' ')
        
        # For now we only deal with equality
        if op == '=':
            if key in values:
                if values[key] == value:
                    return True
            else:
                print >> sys.stderr, "Unknown key: %s" % key
            
        else:
            print >> sys.stderr, "Invalid condition: %s" % condition
            
        return False
    """
    
    def should_display(self):
        """Check if this panel should be displayed.
        """
        for column in self.panel_info['controls']:
            for control in column:
                if self.should_display_child(control):
                    return True
        return False
    
    
    def should_display_child(self, control):
        """Check if a child control should be displayed.
        
        Internal function, not intended for external callers.
        """
        #t1 = self.evaluate_condition(panel['condition'])
        t2 = control['object'].should_display()
        return t2
    
    
    def evt_value_updated(self, key, value, sender=None):
        previous_values = self.get_current_values()
        new_values = copy(previous_values)
        self.update_dict(new_values, {key:value})
    
        if key in self.module_values:
            # A value we have an original for
            original_value = self.module_values[key]
            if key in self.changed_module_values:
                # Has been previously changed
                old_value = self.changed_module_values[key]
                
                if value == original_value:
                    # Changed back to the original
                    del self.changed_module_values[key]
                else:
                    # Changed from the original
                    self.changed_module_values[key] = value
            
            else:
                # Hasn't been previously changed
                if value == original_value:
                    # Hasn't actually changed (e.g. control creation)
                    pass
                else:
                    # First change for this value
                    self.changed_module_values[key] = value
        else:
            # A new value. We don't care if it's already in
            # self.changed_module_values, we need to store it.
            self.changed_module_values[key] = value
                    
        """
        # Do our own checks regarding whether to call update_display
        if self.has_condition_changed(key, previous_values, new_values):
            self.update_display()
        """
        
        # Pass the event along the chain
        if sender != self.parent:
            self.parent.evt_value_updated(key, value, self)

        for column in self.panel_info['controls']:
            for control in column:
                if sender != control['object']:
                    control['object'].evt_value_updated(key, value, self)


    def have_values_changed(self):
        return len(self.get_changed_values()) > 0
    
    
    def get_changed_values(self):
        return copy(self.changed_module_values)
    
    
    def get_current_values(self):
        new = copy(self.module_values)
        self.update_dict(new, self.get_changed_values())
        return new
    
    """
    def has_condition_changed(self, previous_values, new_values):
        for condition in self.conditions:
            prev_result = self.evaluate_condition(condition, previous_values)
            new_result = self.evaluate_condition(condition, new_values)
            if prev_result != new_result:
                return True
        return False
    """
    
    def update_dict(self, target, new_values):
        for key,value in new_values.iteritems():
            if value == None and key in target:
                del target[key]
            else:
                target[key] = value
    
    
    def create_control(self, control):
        if control['type'] == 'text':
            return ac.TextControl(self, control)
        elif control['type'] == 'big_text':
            return ac.BigTextControl(self, control)
        elif control['type'] == 'choice':
            return ac.ListControl(self, control)
        elif control['type'] == 'yes_no':
            return ac.YesNoControl(self, control)
        elif control['type'] == 'button':
            button = wx.Button(self, control['id'], control['label'])
            self.Bind(wx.EVT_BUTTON, control['callback'], id=control['id'])
            return button
        else:
            print >> sys.stderr, "Unknown control type specified: %s" % control['type']
            exit(1)



    def save_values(self):
        self.update_dict(self.module_values, self.get_changed_values())
        self.changed_module_values = {}
    
    
    def reset_displayed_values(self):
        for column in self.panel_info['controls']:
            for control in column:
                if type(control['object']) not in [wx.Button]:
                    control['object'].reset_displayed_value()
